001 /*
002 * Copyright 2005 Stephen J. McConnell
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
013 * implied.
014 *
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018
019 package net.dpml.station.builder;
020
021 import java.io.IOException;
022 import java.net.URI;
023 import java.util.Properties;
024
025 import net.dpml.station.info.RegistryDescriptor;
026 import net.dpml.station.info.RegistryDescriptor.Entry;
027 import net.dpml.station.info.ApplicationDescriptor;
028 import net.dpml.station.info.StartupPolicy;
029
030 import net.dpml.util.DOM3DocumentBuilder;
031
032 import net.dpml.util.DecodingException;
033 import net.dpml.util.Decoder;
034 import net.dpml.util.Resolver;
035 import net.dpml.util.SimpleResolver;
036
037 import net.dpml.lang.ValueDirective;
038 import net.dpml.util.ElementHelper;
039
040 import org.w3c.dom.Document;
041 import org.w3c.dom.Element;
042
043 /**
044 * Test example application sources.
045 *
046 * @author <a href="http://www.dpml.net">Digital Product Meta Library</a>
047 * @version 1.0.2
048 */
049 public final class RegistryBuilder implements Decoder
050 {
051 private static final DOM3DocumentBuilder DOCUMENT_BUILDER =
052 new DOM3DocumentBuilder();
053
054 /**
055 * Build a registry descriptior from a uri.
056 * @param uri the uri to the descriptor XML document
057 * @return the registry descriptor
058 * @exception DecodingException if a decoding error occurs
059 * @exception IOException if a IO error occurs
060 */
061 public Object build( URI uri ) throws DecodingException, IOException
062 {
063 Document document = DOCUMENT_BUILDER.parse( uri );
064 Element root = document.getDocumentElement();
065 Resolver resolver = new SimpleResolver();
066 return decode( root , resolver );
067 }
068
069 /**
070 * Decode a registry descriptior from a DOM element.
071 * @param element the element representing the root registry
072 * @param resolver build-time uri resolver
073 * @return the registry descriptor
074 * @exception DecodingException if a decoding error occurs
075 */
076 public Object decode( Element element, Resolver resolver ) throws DecodingException
077 {
078 String tag = element.getTagName();
079 if( "application".equals( tag ) )
080 {
081 return buildApplicationDescriptor( element, resolver );
082 }
083 else if( "registry".equals( tag ) )
084 {
085 return buildRegistryDescriptor( element, resolver );
086 }
087 else
088 {
089 final String error =
090 "Document element name [" + tag + "] not recognized.";
091 throw new DecodingException( element, error );
092 }
093 }
094
095 private RegistryDescriptor buildRegistryDescriptor(
096 Element element, Resolver resolver ) throws DecodingException
097 {
098 Element[] elements = ElementHelper.getChildren( element );
099 Entry[] entries = new Entry[ elements.length ];
100 for( int i=0; i<elements.length; i++ )
101 {
102 Element elem = elements[i];
103 String key = ElementHelper.getAttribute( elem, "key" );
104 if( null == key )
105 {
106 final String error =
107 "Missing 'key' attribute in application element.";
108 throw new DecodingException( elem, error );
109 }
110 ApplicationDescriptor descriptor = buildApplicationDescriptor( elem, resolver );
111 entries[i] = new Entry( key, descriptor );
112 }
113 return new RegistryDescriptor( entries );
114 }
115
116 private ApplicationDescriptor buildApplicationDescriptor(
117 Element element, Resolver resolver ) throws DecodingException
118 {
119 String title = ElementHelper.getAttribute( element, "title" );
120 StartupPolicy policy = buildStartupPolicy( element );
121 Element jvm = ElementHelper.getChild( element, "jvm" );
122 String base = ElementHelper.getAttribute( jvm, "base" );
123 Element startupElement = ElementHelper.getChild( jvm, "startup" );
124 Element shutdownElement = ElementHelper.getChild( jvm, "shutdown" );
125 int startup = buildTimeout( startupElement, ApplicationDescriptor.DEFAULT_STARTUP_TIMEOUT );
126 int shutdown = buildTimeout( startupElement, ApplicationDescriptor.DEFAULT_SHUTDOWN_TIMEOUT );
127 Element propertiesElement = ElementHelper.getChild( jvm, "properties" );
128 Properties properties = buildProperties( propertiesElement );
129 Element codebase = ElementHelper.getChild( element, "codebase" );
130 URI uri = decodeURI( codebase );
131 Element[] params = ElementHelper.getChildren( codebase, "param" );
132 ValueDirective[] values = buildValueDirectives( params );
133
134 // need to rework ApplicationDescriptor such that the codebase is presented
135 // as an abstract type - e.g. net.dpml.lang.CodeBaseDirective verus
136 // net.dpml.metro.CodeBaseDirective
137
138 return new ApplicationDescriptor(
139 uri, title, values, base, policy, startup, shutdown, properties, null );
140 }
141
142 private URI decodeURI( Element element ) throws DecodingException
143 {
144 String uri = ElementHelper.getAttribute( element, "uri" );
145 if( null == uri )
146 {
147 final String error = "Missing uri attribute.";
148 throw new DecodingException( element, error );
149 }
150 else
151 {
152 try
153 {
154 return new URI( uri );
155 }
156 catch( Exception e )
157 {
158 final String error = "Bad uri argument [" + uri + "].";
159 throw new DecodingException( element, error );
160
161 }
162 }
163 }
164
165 private StartupPolicy buildStartupPolicy( Element element ) throws DecodingException
166 {
167 String policy = ElementHelper.getAttribute( element, "policy" );
168 if( null == policy )
169 {
170 return StartupPolicy.MANUAL;
171 }
172 else
173 {
174 return StartupPolicy.parse( policy );
175 }
176 }
177
178 private int buildTimeout( Element element, int fallback ) throws DecodingException
179 {
180 if( null == element )
181 {
182 return fallback;
183 }
184 else
185 {
186 String value = ElementHelper.getValue( element );
187 if( null == value )
188 {
189 return fallback;
190 }
191 else
192 {
193 return Integer.parseInt( value );
194 }
195 }
196 }
197
198 private Properties buildProperties( Element element ) throws DecodingException
199 {
200 Properties properties = new Properties();
201 if( null == element )
202 {
203 return properties;
204 }
205 else
206 {
207 Element[] children = ElementHelper.getChildren( element );
208 for( int i=0; i<children.length; i++ )
209 {
210 Element child = children[i];
211 String name = ElementHelper.getAttribute( child, "name" );
212 if( null == name )
213 {
214 final String error =
215 "Property declaration does not contain a 'name' attribute.";
216 throw new DecodingException( child, error );
217 }
218 else
219 {
220 String value = ElementHelper.getAttribute( child, "value" );
221 properties.setProperty( name, value );
222 }
223 }
224 return properties;
225 }
226 }
227
228 /**
229 * Construct a value directive array.
230 * @param elements the array of DOM elements representing value directive assertions
231 * @return the array of value directives
232 */
233 protected ValueDirective[] buildValueDirectives( Element[] elements )
234 {
235 ValueDirective[] values = new ValueDirective[ elements.length ];
236 for( int i=0; i<elements.length; i++ )
237 {
238 values[i] = buildValueDirective( elements[i] );
239 }
240 return values;
241 }
242
243 /**
244 * Construct a single value directive.
245 * @param element the DOM element representing the value directive assertions
246 * @return the value directive
247 */
248 protected ValueDirective buildValueDirective( Element element )
249 {
250 String classname = ElementHelper.getAttribute( element, "class" );
251 String method = ElementHelper.getAttribute( element, "method" );
252 Element[] elements = ElementHelper.getChildren( element, "param" );
253 if( elements.length > 0 )
254 {
255 ValueDirective[] values = buildValueDirectives( elements );
256 return new ValueDirective( classname, method, values );
257 }
258 else
259 {
260 String value = ElementHelper.getAttribute( element, "value" );
261 return new ValueDirective( classname, method, value );
262 }
263 }
264 }